/**
 * 
 */
package edu.gtcfla.km.admin.appmodules.web;

import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.ListIterator;
import java.util.Set;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import net.sf.json.JsonConfig;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import org.vsg.biz.BusinessEntityFactory;
import org.vsg.biz.account.Menu;
import org.vsg.biz.account.Url;
import org.vsg.common.i18n.I18nMessageService;
import org.vsg.common.web.json.ListResult;
import org.vsg.common.web.json.SubmitResult;
import org.vsg.common.web.json.TreeNodeColumn;
import org.vsg.common.web.json.processor.JsDateViewJsonValueProcessor;
import org.vsg.module.resources.component.AssociationClass;
import org.vsg.module.resources.component.Module;
import org.vsg.module.resources.web.discover.ModuleDiscoveryService;

import edu.gtcfla.km.admin.appmodules.service.MenuResourceService;
import edu.gtcfla.km.admin.appmodules.service.RegisterResourceService;
import edu.gtcfla.km.admin.appmodules.service.UrlManagerService;
import edu.gtcfla.km.admin.appmodules.vo.RegisterMenuResourceView;
import edu.gtcfla.km.admin.appmodules.vo.RegisterUrlResourceView;

/**
 * @author Bill Vison
 *
 */
@Controller
@Lazy
@RequestMapping("/apps_sysadmin")
public class ResourceController {

	
	private final static Logger logger = LoggerFactory.getLogger(ResourceController.class);
	

	@Autowired(required =false)
	private ModuleDiscoveryService moduleDiscoveryService;
	
	@Autowired(required =false)
	private RegisterResourceService registerResourceService;
	
	@Autowired(required =false)
	private MenuResourceService sysMenuResourceService;

	@Autowired(required =false)
	private UrlManagerService sysUrlResourceService;

	@Autowired	
	private BusinessEntityFactory entityFactory;	
	
	@Autowired
	private I18nMessageService i18nMessageService;
			

	private String modulePrefix = "/apps_sysadmin/resources";

	@RequestMapping(value = "/resources/regresdashboard.htm")
	public ModelAndView showDashboard() throws Exception {


		ModelAndView mav = new ModelAndView();
		mav.setViewName( modulePrefix + "/regresdashboard"); // view name

		return mav;

	}	

	@RequestMapping(value = "/data/resource/regmodules.json")
	public ModelAndView showRegModulesTree()
			throws Exception {
		
		Set<String> groupIds = moduleDiscoveryService.listAllModuleGroupIds();
		
		
		Set<TreeNodeColumn> module = getModuleTree(groupIds);
		
		JsonConfig jcfg = new JsonConfig();	
		jcfg.registerJsonValueProcessor(java.util.Date.class,new JsDateViewJsonValueProcessor());
		JSONArray jsonObject = JSONArray.fromObject(module, jcfg);		
		

		ModelAndView mav = new ModelAndView();
		mav.addObject("json", jsonObject);
		mav.setViewName("result"); // view name
        
		return mav;

	}
	
	
	@RequestMapping(value = "/data/resource/menres.json")
	public ModelAndView accessMenuResource(String moduleId , String menuName)
			throws Exception {
		
		Set<RegisterMenuResourceView> regMenuResView = new LinkedHashSet<RegisterMenuResourceView>();
		if (menuName == null) {
			regMenuResView = registerResourceService.listAndShowMenuResourcesViewInModule(moduleId);
		}
		
		
		ListResult listResult = new ListResult();
		listResult.setRows( regMenuResView );
		listResult.setResults( regMenuResView.size() );
		
		JsonConfig jcfg = new JsonConfig();	
		jcfg.registerJsonValueProcessor(java.util.Date.class,new JsDateViewJsonValueProcessor());
		JSONObject jsonObject = JSONObject.fromObject(listResult, jcfg);			
		
		
		// --- reflesh ----

		ModelAndView mav = new ModelAndView();
		mav.addObject("json", jsonObject);
		mav.setViewName("result"); // view name
        
		return mav;

	}

	@RequestMapping(value = "/data/resource/urlres.json")
	public ModelAndView accessUrlResource(String moduleId , String urllink)
			throws Exception {
		
		Set<RegisterUrlResourceView> regAssoCls = new LinkedHashSet<RegisterUrlResourceView>();
		if (urllink == null) {
			regAssoCls = registerResourceService.listAndShowUrlResourcesViewInModule(moduleId);
		}
		
		ListResult listResult = new ListResult();
		listResult.setRows( regAssoCls );
		listResult.setResults( regAssoCls.size() );
		
		JsonConfig jcfg = new JsonConfig();	
		jcfg.registerJsonValueProcessor(java.util.Date.class,new JsDateViewJsonValueProcessor());
		JSONObject jsonObject = JSONObject.fromObject(listResult, jcfg);	
		
		// --- reflesh ----
		ModelAndView mav = new ModelAndView();
		mav.addObject("json", jsonObject);
		mav.setViewName("result"); // view name
        
		return mav;
	}
	
	// ---- convert to url resource ---
	private Set<Url> convertRegAssoUrlRes(Set<AssociationClass> regAssoCls) {
		
		Set<Url> urlReses = new LinkedHashSet<Url>();
		for (AssociationClass rac : regAssoCls) {
			Url urlRes = entityFactory.create(Url.class);
			urlRes.setCode(rac.getId());
		}
		
		
		
		return urlReses;
	}
	
	
	
	@RequestMapping(value = "/data/resource/resmoddimensional.json")
	public ModelAndView accessResModuleDimensional()
			throws Exception {
		
		Set<String> groupIds = moduleDiscoveryService.listAllModuleGroupIds();
		
		Set<TreeNodeColumn> module = extendAllModules(groupIds);
		
		JsonConfig jcfg = new JsonConfig();	
		jcfg.registerJsonValueProcessor(java.util.Date.class,new JsDateViewJsonValueProcessor());
		JSONArray jsonObject = JSONArray.fromObject(module, jcfg);

		// --- reflesh ----

		ModelAndView mav = new ModelAndView();
		mav.addObject("json", jsonObject);
		mav.setViewName("result"); // view name
        
		return mav;
	}
	
	
	// --- extend show menu ---
	private Set<TreeNodeColumn> extendAllModules(Set<String> groupIds) {
		
		Set<TreeNodeColumn> groupSet = new LinkedHashSet<TreeNodeColumn>();
		
		for (Iterator<String> groupIdsIter = groupIds.iterator() ; groupIdsIter.hasNext() ; ) {
			String groupId = groupIdsIter.next();
			
			Set<Module> modules = moduleDiscoveryService.findRegisterModulesInGroup(groupId);
			

			for (Iterator<Module> modulesIter = modules.iterator() ; modulesIter.hasNext() ; ) {
				
				Module module = modulesIter.next();
				
				String moduleId = module.getGroupdId()+"."+module.getNamdId();
				
				TreeNodeColumn subtnc = new TreeNodeColumn();
				subtnc.setText( module.getDescription() + "(" + groupId + ") ");
				subtnc.setId( moduleId );
				subtnc.setLeaf(true);
				
				groupSet.add( subtnc );
			}
			
		}
		
		return groupSet;		
	}
	

	@RequestMapping(value = "/data/resource/regmenu.act")
	public ModelAndView processRegisterMenu( String jsonData)
			throws Exception {
		
		// --- map to json object data ---
		SubmitResult result = new SubmitResult();
		if (jsonData == null ) {
			result.setSuccess( false );
			String msg = i18nMessageService.getMessage("crm.module-admin.regmenu.error", null);
			result.setMsg(msg);					
		} else {

			JSONArray jsonArray = JSONArray.fromObject( jsonData );			
			
			@SuppressWarnings("unchecked")
			ListIterator<JSONObject> li = (ListIterator<JSONObject>) jsonArray.listIterator();
			
			Set<Menu> menuResSet = new LinkedHashSet<Menu>();
			Menu smRes = null;
			while ( li.hasNext() ) {
				JSONObject obj = li.next();
				String menuCode = obj.getString("code") ;
				smRes = entityFactory.create(Menu.class);
				
				smRes.setModuleId( registerResourceService.getModuleIdByRegMenuCode( menuCode ) );
				smRes.setCode( menuCode );
				smRes.setName( obj.getString("name") );
				
				menuResSet.add( smRes );
			}
			
			sysMenuResourceService.registerNewMenuResource(menuResSet);
			
			result.setSuccess(true);
			String msg = i18nMessageService.getMessage("crm.module-admin.regmenu.success", null);
			result.setMsg(msg);
			
		}

		
		JsonConfig jcfg = new JsonConfig();	
		jcfg.registerJsonValueProcessor(java.util.Date.class,new JsDateViewJsonValueProcessor());
		JSONObject jsonObject = JSONObject.fromObject(result, jcfg);		
		
		// --- reflesh ----

		ModelAndView mav = new ModelAndView();
		mav.addObject("json", jsonObject);
		mav.setViewName("result"); // view name
        
		return mav;
	}

	@RequestMapping(value = "/data/resource/regurl.act")
	public ModelAndView processRegisterUrl(String jsonData)
			throws Exception {
		

		// --- map to json object data ---
		SubmitResult result = new SubmitResult();
		if (jsonData == null ) {
			result.setSuccess( false );
			
			String msg = i18nMessageService.getMessage("crm.module-admin.regurl.error", null);
			result.setMsg(msg);			
		} else {

			JSONArray jsonArray = JSONArray.fromObject( jsonData );			
			
			@SuppressWarnings("unchecked")
			ListIterator<JSONObject> li = (ListIterator<JSONObject>) jsonArray.listIterator();
			
			Set<Url> urlResSet = new LinkedHashSet<Url>();
			Url urlRes = null;
			while ( li.hasNext() ) {
				JSONObject obj = li.next();
				String code = obj.getString("code") ;
				urlRes = entityFactory.create(Url.class);
				
				AssociationClass rac = registerResourceService.getRegAssoClassByKeyId( code );
				Module module = rac.getModule();
				
				urlRes.setModuleId( module.getGroupdId()+"."+ module.getNamdId() );
				urlRes.setCode( rac.getFullKey() );
				urlRes.setLink( obj.getString("link") );
				urlRes.setType("internal");
				
				urlResSet.add( urlRes );
			}
			
			sysUrlResourceService.registerNewUrlResource(urlResSet);

			result.setSuccess(true);
			String msg = i18nMessageService.getMessage("crm.module-admin.regurl.success", null);
			result.setMsg(msg);
			
		}

		
		JsonConfig jcfg = new JsonConfig();	
		jcfg.registerJsonValueProcessor(java.util.Date.class,new JsDateViewJsonValueProcessor());
		JSONObject jsonObject = JSONObject.fromObject(result, jcfg);		
		
		// --- reflesh ----

		ModelAndView mav = new ModelAndView();
		mav.addObject("json", jsonObject);
		mav.setViewName("result"); // view name
        
		return mav;
	}	
	
	/**
	 * not use handle ---
	 * @return
	 * @throws Exception
	 */
	@RequestMapping(value = "/data/resource/unregmenu.act")
	public ModelAndView processUnregisterMenu()
			throws Exception {
		
		Set<String> groupIds = moduleDiscoveryService.listAllModuleGroupIds();
		
		
		Set<TreeNodeColumn> module = getModuleTree(groupIds);
		
		JsonConfig jcfg = new JsonConfig();	
		jcfg.registerJsonValueProcessor(java.util.Date.class,new JsDateViewJsonValueProcessor());
		JSONArray jsonObject = JSONArray.fromObject(module, jcfg);		
		
		
		// --- reflesh ----

		ModelAndView mav = new ModelAndView();
		mav.addObject("json", jsonObject);
		mav.setViewName("result"); // view name
        
		return mav;
	}	
	
	@RequestMapping(value = "/data/resource/refleshcache.act")
	public ModelAndView processRefleshCache()
			throws Exception {
		
		
		this.registerResourceService.refleshCache();

		// --- map to json object data ---
		SubmitResult result = new SubmitResult();		
		result.setSuccess( true );
		String msg = i18nMessageService.getMessage("crm.module-admin.refleshcache.success", null);
		result.setMsg(msg);
		
		JsonConfig jcfg = new JsonConfig();	
		jcfg.registerJsonValueProcessor(java.util.Date.class,new JsDateViewJsonValueProcessor());
		JSONObject jsonObject = JSONObject.fromObject(result, jcfg);		
		
		
		// --- reflesh ----
		ModelAndView mav = new ModelAndView();
		mav.addObject("json", jsonObject);
		mav.setViewName("result"); // view name
        
		return mav;
	}	
	
	
	private Set<TreeNodeColumn> getModuleTree(Set<String> groupIds) {
		
		
		Set<TreeNodeColumn> groupSet = new LinkedHashSet<TreeNodeColumn>();
		
		for (Iterator<String> groupIdsIter = groupIds.iterator() ; groupIdsIter.hasNext() ; ) {
			String groupId = groupIdsIter.next();
			
			Set<Module> modules = moduleDiscoveryService.findRegisterModulesInGroup(groupId);
			
			Set<TreeNodeColumn> moduleSets = new LinkedHashSet<TreeNodeColumn>();

			for (Iterator<Module> modulesIter = modules.iterator() ; modulesIter.hasNext() ; ) {
				
				Module module = modulesIter.next();
				
				String moduleId = module.getGroupdId()+"."+module.getNamdId();
				
				TreeNodeColumn subtnc = new TreeNodeColumn();
				subtnc.setText( module.getDescription() );
				subtnc.setId( moduleId );
				subtnc.setLeaf(true);
				
				moduleSets.add( subtnc );
			}

			TreeNodeColumn tnc = new TreeNodeColumn();
			tnc.setText( groupId );
			tnc.setId( groupId );
			tnc.setChildren( moduleSets );
			
			groupSet.add(tnc);	
			
		}
		
		return groupSet;
	}
	
	
	
	
}
